package com.tansun.easycare.rule.scoremodel.service.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.converters.DateConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.tansun.easycare.rule.common.CommonEnum;
import com.tansun.easycare.rule.common.model.BaseBean;
import com.tansun.easycare.rule.common.model.RuleSetParamInfo;
import com.tansun.easycare.rule.common.model.SelectEditorVo;
import com.tansun.easycare.rule.common.rulebasebean.Action;
import com.tansun.easycare.rule.common.rulebasebean.BlankFact;
import com.tansun.easycare.rule.common.rulebasebean.DThen;
import com.tansun.easycare.rule.common.rulebasebean.DWhen;
import com.tansun.easycare.rule.common.rulebasebean.Fact;
import com.tansun.easycare.rule.common.rulebasebean.RuleCollection;
import com.tansun.easycare.rule.common.rulebasebean.RuleItem;
import com.tansun.easycare.rule.common.service.DataBomService;
import com.tansun.easycare.rule.common.service.impl.RuleBaseServiceImpl;
import com.tansun.easycare.rule.datamodel.entity.RuleDataparams;
import com.tansun.easycare.rule.datamodel.service.DataModelService;
import com.tansun.easycare.rule.datamodel.service.RuleDataparamsService;
import com.tansun.easycare.rule.decisiontree.entity.RuleTreeParam;
import com.tansun.easycare.rule.exception.BizException;
import com.tansun.easycare.rule.referencedata.entity.RuleReferenceData;
import com.tansun.easycare.rule.referencedata.service.RuleReferenceDataService;
import com.tansun.easycare.rule.rulegroup.model.RuleExpessVO;
import com.tansun.easycare.rule.rulegroup.model.RuleSetExpressVO;
import com.tansun.easycare.rule.rulegroup.service.RuleParseExpService;
import com.tansun.easycare.rule.rulemange.entity.RuleManage;
import com.tansun.easycare.rule.rulemange.service.RuleManageService;
import com.tansun.easycare.rule.ruleversion.entity.RuleVersioninfo;
import com.tansun.easycare.rule.ruleversion.service.RuleVersioninfoService;
import com.tansun.easycare.rule.scoremodel.dao.RuleScoreDao;
import com.tansun.easycare.rule.scoremodel.entity.RuleScore;
import com.tansun.easycare.rule.scoremodel.entity.RuleScoreInfo;
import com.tansun.easycare.rule.scoremodel.model.ScoreEntity;
import com.tansun.easycare.rule.scoremodel.model.ScoreItem;
import com.tansun.easycare.rule.scoremodel.service.RuleScoreInfoService;
import com.tansun.easycare.rule.scoremodel.service.ScoreModelService;
import com.tansun.easycare.rule.utils.DroolsUtils;
import com.tansun.rule.common.RuleModelTypeEnum;
import com.tansun.rule.model.toolbean.CardFact;
import com.tansun.rule.model.toolbean.NumericFact;
import com.tansun.rule.utils.StringUtils;

@Service("scoreModelService")
public class ScoreModelServiceImpl extends RuleBaseServiceImpl<RuleScoreDao, RuleScore> implements ScoreModelService {
    @Autowired
    private RuleManageService ruleManageService;
    @Autowired
    private RuleVersioninfoService ruleVersioninfoService;
    @Autowired
    private RuleScoreInfoService ruleScoreInfoService;
    @Autowired
    private RuleReferenceDataService ruleReferenceDataService;
	@Autowired
	private  DataBomService dataBomService;
	@Autowired
	private  RuleDataparamsService  ruleDataparamsService;
    @Autowired
    private DataModelService dataModelService;
    @Autowired
    RuleParseExpService ruleParseExpService;
    
    /**
     * 保存更新评分模型
     */
    public void saveOrUpdate(ScoreEntity scoreEntity) throws Exception {
        RuleManage ruleManage = scoreEntity.getScoreModel();
        ruleManage.setStatus("1");
        ruleManage.setModelType(RuleModelTypeEnum.ScoreModel.getCode());
        ruleManage = ruleManageService.saveOrUpdate(ruleManage);
        dataModelService.saveOrUpdateBuiltinParam(ruleManage.getCode(),ruleManage.getName(), RuleModelTypeEnum.ScoreModel.code, ruleManage.getProjectCode(),ruleManage.getCreateBy());
        List<ScoreItem> indexList = scoreEntity.getTreeList();
        List<RuleDataparams> funcparamList = new ArrayList<RuleDataparams>();
        String context = writeDrl(ruleManage, indexList,funcparamList);
        /** 函数模式**/
        //String context = writeDrlJavaFunc(ruleManage, indexList,funcparamList);
        if (context == null) {
            throw new BizException("未产生drl内容");
        }
        this.ruleReferenceDataService.saveReferenceDataFuncRef(funcparamList,ruleManage);
        RuleVersioninfo ruleVersioninfo = new RuleVersioninfo();
        
        ruleVersioninfo.init(ruleManage, context);
        ruleVersioninfo.setDatasetNames(scoreEntity.getDatasetNames());
        this.ruleVersioninfoService.save(ruleVersioninfo);
        List<RuleScore> scoreitemList = new ArrayList<RuleScore>();
        List<RuleScoreInfo> itemInfoList = new ArrayList<RuleScoreInfo>();
        //收集引用数据
        Map<String, RuleReferenceData> refMap = new HashMap<String, RuleReferenceData>();
    	Map<String, RuleDataparams> funcparamMap = new HashMap<String, RuleDataparams>();	
        String key = "";
        String paramType = "";
        int k = 0;
        for (ScoreItem item : scoreEntity.getTreeList()) {
            scoreitemList.add(item);
            key = item.getClassName() + "|" + item.getNameen();
            paramType = "in";
            if ("scoreSummary".equals(item.getContentType()) || "scoreSection".equals(item.getContentType())) {
                paramType = "out";
            }
            key += "|" + paramType;
            ruleReferenceDataService.collectCommonData(item, key, paramType, ruleManage, refMap);
            if (item.getList() != null && item.getList().size() > 0) {
                for (RuleScoreInfo ruleScoreInfo : item.getList()) {
                    ruleScoreInfo.setParentTreeId(item.getTreeId());
                    if(StringUtils.isNotEmpty(ruleScoreInfo.getFormula())) {
                    	this.ruleParseExpService.transformFactReference(ruleScoreInfo.getFormula(), ruleManage, refMap, funcparamMap);//收集引用变量
                    }
                }
                itemInfoList.addAll(item.getList());
            }
        }
		key = "builtinParam" + "|"+ ruleManage.getCode() + "|out";
		RuleTreeParam ruleParam = new RuleTreeParam();
		ruleParam.setClassName("builtinParam");
		ruleParam.setNamecn(ruleManage.getName()+"_模型名称");
		ruleParam.setNameen(ruleManage.getCode());
		ruleParam.setDataType("String");
		ruleReferenceDataService.collectCommonData(ruleParam, key, "out", ruleManage, refMap);
        //保存数据数据
        this.ruleReferenceDataService.saveReferenceData(refMap);
		//保存函数变量
        List<RuleDataparams> ruleParamdatas = new ArrayList<>(funcparamMap.values());
        this.ruleReferenceDataService.saveReferenceDataFuncRef(ruleParamdatas,ruleManage);
        
        this.insertBatch(scoreitemList, new String[]{"id", "manageId", "projectCode", "version"},
                new Object[]{null, ruleManage.getId(), ruleManage.getProjectCode(), ruleManage.getVersion()}, true);
        if (itemInfoList.size() > 0){
            ruleScoreInfoService.insertBatch(itemInfoList, new String[]{"id", "manageId", "projectCode", "version"},
                    new Object[]{null, ruleManage.getId(), ruleManage.getProjectCode(), ruleManage.getVersion()}, true);
        }
    }

    /**
     * 显示java代码
     * @param tableEntity
     * @throws BizException
     */
    public String showJavaCode(ScoreEntity scoreEntity) throws BizException{
		return null;
/*    	RuleManage ruleManage = scoreEntity.getScoreModel();
    	ruleManage = ruleManageService.get(ruleManage);
    	scoreEntity.setScoreModel(ruleManage);
    	funcParamMap = ruleDataparamsService.getdataparams(ruleManage.getProjectCode());
    	
    	ScoreEntitySC scoreEntitySC = ClassChangeUtils.changeScoreEntityClass(scoreEntity);
    	return ScoreModelCreate.createCode(scoreEntitySC, funcParamMap);*/
    }
    
    private static double treeId2Double(String treeId) {
    	double bit = 100;
        String[] treeId1 = treeId.split("-");
        double data = 0;
        int len = treeId1.length;
        for(String tree:treeId1) {
        	data += Double.parseDouble(tree)*Math.pow(bit,len-1);
        }
        return data;
    }
    /**
     * 获取评分模型信息
     */
    public List<ScoreItem> getScoreItems(String scoreId, String version) throws Exception {
        List<ScoreItem> resultList = new ArrayList<ScoreItem>();
 
        RuleScore scoreCon = new RuleScore();
        scoreCon.setManageId(scoreId);
        scoreCon.setVersion(version);
        List<RuleScore> scoreItems = this.findList(scoreCon);

        RuleScoreInfo scoreInfoCon = new RuleScoreInfo();
        scoreInfoCon.setManageId(scoreId);
        scoreInfoCon.setVersion(version);
        List<RuleScoreInfo> scoreInfoItems = ruleScoreInfoService.findList(scoreInfoCon);
        Comparator<RuleScoreInfo> comparator =  new Comparator<RuleScoreInfo>() {
            @Override  
            public int compare(RuleScoreInfo o1, RuleScoreInfo o2) {  
                if(StringUtils.isEmpty(o1.getTreeId()) || StringUtils.isEmpty(o2.getTreeId())){  
                    return -1;  
                }
                Double data1 = treeId2Double(o1.getTreeId());
                Double data2 = treeId2Double(o2.getTreeId());
                return  data1.compareTo(data2); 
            }
        };
        
        for (RuleScore ruleScore : scoreItems) {
            ScoreItem item = new ScoreItem();
            ConvertUtils.register(new DateConverter(null), java.util.Date.class);
            BeanUtils.copyProperties(item, ruleScore);
            if (item.getContentType().equals(CommonEnum.ScoreModelType.scoreDetail.toString()) && !item.getNameen().equals("initialScore")) {
                for (RuleScoreInfo ruleScoreInfo : scoreInfoItems) {
                    if (item.getTreeId().equals(ruleScoreInfo.getParentTreeId()))
                        item.getList().add(ruleScoreInfo);
                }
            }
            Collections.sort(item.getList(), comparator);
            resultList.add(item);
        }
        Collections.sort(resultList,new Comparator<RuleScore>() {
            @Override  
            public int compare(RuleScore o1, RuleScore o2) {  
                if(StringUtils.isEmpty(o1.getTreeId()) || StringUtils.isEmpty(o2.getTreeId())){  
                    return -1;  
                }  
                Double data1 = treeId2Double(o1.getTreeId());
                Double data2 = treeId2Double(o2.getTreeId());
                return  data1.compareTo(data2); 
            }  
        });

        return resultList;
    }

    /**
     * 状态更改
     */
    public void statusChange(RuleManage score) throws Exception {

    }

    public SelectEditorVo[] getSelectListByType(String modelName) throws Exception {
        return null;
    }

    private String writeDrl(RuleManage score, List<ScoreItem> scoreItem,List<RuleDataparams> funcparamList) throws Exception {
        if (scoreItem == null || scoreItem.size() == 0)
            return null;
        funcParamMap = ruleDataparamsService.getdataparams(score.getProjectCode());
        RuleCollection ruleCollection = new RuleCollection();
        ruleCollection.setDrlName(score.getCode());
        ruleCollection.setObjName(score.getName());
        ruleCollection.setContentType(RuleCollection.RULESCORE);
        ruleCollection.setVersion(score.getVersion());
        //生成动作组 从1开始递减
        int priority = 1;
        int summaryCount = 0;
        RuleItem initRuleItem = null;
        for (ScoreItem item : scoreItem) {
            RuleItem ruleItem;
            String groupName = UUID.randomUUID().toString();
            String whenStr = "";
            String thenStr = "";
            String ruleName = "";
            String ruleResultInfo = "";
            //如果是初始评分则特殊处理  //创建初始分数规则（card_init）1000
            if (!StringUtils.isEmpty(item.getClassName()) && item.getClassName().equals("InitialScore")) {
                thenStr = "drools.insert(new ScoreCardObj(\"" + score.getName() + "\",\"" + score.getCode() + "\"," + item.getScoreParam() +  ",\"#{formula}\",false,droolsRuleLog,drools));";
                thenStr += "//droolsRuleLog.addLogs";
                ruleItem = getCustomRule("card_init", 1000, null, thenStr);
                initRuleItem = ruleItem;
                ruleCollection.getListItem().add(ruleItem);
                continue;
            }
            if (item.getList() != null && item.getList().size() > 0) {
                for (RuleScoreInfo child : item.getList()) {
                    //如果是scoreDetail的
                    //返回每个动作组的输出变量 * 该动作组的评分系数
                    if (child.getTreeId() != null && child.getTreeId().length() > 0) {
                        ruleName = "score_" + child.getTreeId();
                    } else {
                        ruleName = "score_" + StringUtils.generateTenUuid();
                    }
                    List<String> whenList = new ArrayList<String>();
                    whenList.add("scoreCardObj:ScoreCardObj()");
                    String formualtemp = null;
                    String tempStr = null;
                    if ("1".equals(child.getIsOther())) {
                        whenStr = "";
                    } else {
                        whenStr = getScoreDetailDrl(item, child, "when", null, funcparamList,false);
                    }
                    if ("2".equals(child.getSectionType())) {
                        //formualtemp = "MathHelper.invokeMath($insertMap,metaMap,\"" + child.getFormula() + "\")";
                    	formualtemp = ruleParseExpService.parseAction(child.getFormula(), false, this);
                    	if(StringUtils.isNotEmpty(formualtemp)) {
    	                	formualtemp = formualtemp.trim();
    	                	if(formualtemp.endsWith(";")) {
    	                		formualtemp = formualtemp.substring(0,formualtemp.lastIndexOf(";"));
    	                	}
                    	}else {
                    		formualtemp = "";
                    	}
                    } else if ("4".equals(child.getSectionType())) {//正向：系数*（变量-下限值）/（变量分数-下限）
                        tempStr = ",\n temp:(" + item.getScoreParam() + "*(this[\"" + item.getClassName() + "\"][\"" + item.getNameen() + "\"]-(" + child.getLowerVal() + "))/(" + child.getScoreVal() + "-(" + child.getLowerVal() + ")))";
                    } else if ("6".equals(child.getSectionType())) {//反向：系数*（上限-变量）/（上限-变量分数）
                        tempStr = ",\n temp:(" + item.getScoreParam() + "*(" + child.getUpperVal() + "-(this[\"" + item.getClassName() + "\"][\"" + item.getNameen() + "\"]))/(" + child.getUpperVal() + "-(" + child.getScoreVal() + ")))";
                    }
                    if (tempStr != null) {
                        whenStr += tempStr;
                        formualtemp = "temp";
                    }
                    thenStr = getScoreDetailDrl(item, child, "then", formualtemp, funcparamList,false);
                    whenList.add(whenStr);
                    ruleItem = getCustomRule(ruleName, priority, whenList, thenStr);
                    ruleItem.setActivationGroup(groupName);
                    ruleCollection.getListItem().add(ruleItem);
                    priority--;
                }
            }else if(item.getTreeId()!=null){
            	ruleName = "score_" + item.getTreeId();
            	String name = item.getClassName() + "." + item.getNameen();
            	NumericFact data = new NumericFact(name);
            	CardFact fact = new CardFact(name, name, item.getScoreParam()+"","Double.parseDouble("+ data+".toString())");
            	List<String> whenList = new ArrayList<String>();
                whenList.add("scoreCardObj:ScoreCardObj()");
            	ruleItem = getCustomRule(ruleName, priority, whenList, fact.toString());
            	ruleCollection.getListItem().add(ruleItem);
            	priority--;
            } else {
                List<String> whenList = new ArrayList<String>();
                whenList.add("scoreCardObj:ScoreCardObj()");
                thenStr = "ruleHelper.setValue";
                if ("List".equals("")) {
                    thenStr = "ruleHelper.insertValue";
                }
                if (summaryCount == 0) {
                    thenStr += "($insertMap,\"" + item.getClassName() + "." + item.getNameen() + "\",scoreCardObj.value);\n";
                    thenStr += "ruleHelper.setValue($insertMap,\"builtinParam."+score.getCode()+"\",\""+score.getName()+"\")";
                    ruleResultInfo = "scoreCardObj.value";
                    Action action = initRuleItem.getdThen().getListAction().get(0);
                    String replaceThenStr = action.getContent();
                    String formula = parseFormula(item.getFormula());
                    action.setContent(replaceThenStr.replace("#{formula}", formula));
				}
//                else if(summaryCount==1){
//					thenStr += "($insertMap,\""+item.getClassName() +"." + item.getNameen() + "\",\""+score.getName()+"\");";
//                } 
                else {
                    //thenStr = "MathHelper.invokeMathToObj($insertMap,metaMap,\"" + item.getClassName() + "." + item.getNameen() + "\",\"" + item.getFormula() + "\");";
                	String formualtemp = ruleParseExpService.parseAction(item.getFormula(), false, this);
                	if(StringUtils.isNotEmpty(formualtemp)) {
	                	formualtemp = formualtemp.trim();
	                	if(formualtemp.endsWith(";")) {
	                		formualtemp = formualtemp.substring(0,formualtemp.lastIndexOf(";"));
	                	}
                	}else {
                		formualtemp = "null";
                	}
                	thenStr = "ruleHelper.setValue($insertMap,\"" + item.getClassName() + "." + item.getNameen() + "\"," + formualtemp + ");";
                }
                groupName = "";
                summaryCount++;
                ruleName = "score_" + StringUtils.generateTenUuid();
                ruleItem = getCustomRule(ruleName, priority, whenList, thenStr);
                ruleItem.setRuleResultInfo(ruleResultInfo);
                ruleItem.setActivationGroup(groupName);
                ruleCollection.getListItem().add(ruleItem);
                priority--;
            }
        }
        //规则输出描述（card_ouputDesc）-998
        List<String> whenList = new ArrayList<String>();
        whenList.add("scoreCardObj:ScoreCardObj(this.isOut == true)");
        String actionStr = "scoreCardObj.inInsertMap($insertMap);";
        RuleItem rule = getCustomRule("card_ouputDesc", -998, whenList, actionStr);
        ruleCollection.getListItem().add(rule);
        //规则对象撤销 (card_end)-999
        whenList = new ArrayList<String>();
        whenList.add("scoreCardObj:ScoreCardObj()");
        actionStr = "drools.retract(scoreCardObj);";
        actionStr += "//droolsRuleLog.addLogs";
        rule = getCustomRule("card_end", -999, whenList, actionStr);
        ruleCollection.getListItem().add(rule);
        //写入DRL文件
        return DroolsUtils.convert2Drl(ruleCollection);
    }

    private String parseFormula(String actionStr) {
    	List<RuleSetExpressVO> ruleSet = JSON.parseArray(actionStr, RuleSetExpressVO.class);
		RuleSetExpressVO ruleSetExpressVO = null;
		RuleExpessVO ruleExpessVO = null;
		StringBuffer strBuf = new StringBuffer();
		String datasetName = "";
		String fieldName = "";
		for (int i = 0; i < ruleSet.size(); i++) {
			ruleSetExpressVO = ruleSet.get(i);
			StringBuffer lineBuf = new StringBuffer();
			List<RuleExpessVO>  action = ruleSetExpressVO.getAction();
			for (int j = 0; j < action.size(); j++) {
				ruleExpessVO = action.get(j);
				if (BaseBean.TYPE_BOM.equals(ruleExpessVO.getType())) {
					datasetName = ruleExpessVO.getName();
					j = j + 1;
					ruleExpessVO = ruleSetExpressVO.getAction().get(j);
					//针对变量
					if (BaseBean.OBJ_TYPE_FIELD.equals(ruleExpessVO.getType())) {
						fieldName = ruleExpessVO.getName();
						lineBuf.append("#{" + datasetName + "." + fieldName +"}");
					}
				} else if (BaseBean.TYPE_SYMBOL.equals(ruleExpessVO.getType()) && !ruleExpessVO.getName().equals(";")) {
					lineBuf.append(ruleExpessVO.getDrlSymbol());
				}else if (BaseBean.OBJ_TYPE_VALUE.equals(ruleExpessVO.getType())) {
					lineBuf.append(ruleExpessVO.getValue());
				}else if(BaseBean.TYPE_JFUN.equals(ruleExpessVO.getType())){
					lineBuf.append(ruleExpessVO.getDrlName().replace("(", ""));
				}else if(BaseBean.OBJ_FUNC_OPT.equals(ruleExpessVO.getType())) {
					lineBuf.append(ruleExpessVO.getName());
				}else if(BaseBean.OBJ_TYPE_FIELD.equals(ruleExpessVO.getType())) {
					lineBuf.append(ruleExpessVO.getName());
				}
			}
			strBuf.append(lineBuf.toString());
		}
		return strBuf.toString();
	}

	private String writeDrlJavaFunc(RuleManage score, List<ScoreItem> scoreItem,List<RuleDataparams> funcparamList) throws Exception {
        if (scoreItem == null || scoreItem.size() == 0)
            return null;
        funcParamMap = ruleDataparamsService.getdataparams(score.getProjectCode());
        RuleCollection ruleCollection = new RuleCollection();
        ruleCollection.setDrlName(score.getCode());
        ruleCollection.setObjName(score.getName());
        ruleCollection.setContentType(RuleCollection.RULESCORE);
        ruleCollection.setVersion(score.getVersion());
        //生成动作组 从1开始递减
        int priority = 1;
        int summaryCount = 0;
        for (ScoreItem item : scoreItem) {
            RuleItem ruleItem;
            String groupName = UUID.randomUUID().toString();
            String whenStr = "";
            String thenStr = "";
            String ruleName = "";
            String ruleResultInfo = "";
            //如果是初始评分则特殊处理  //创建初始分数规则（card_init）1000
            if (!StringUtils.isEmpty(item.getClassName()) && item.getClassName().equals("InitialScore")) {
                thenStr = "ScoreCardObj scoreCardObj = new ScoreCardObj(\"" + score.getName() + "\",\"" + score.getCode() + "\"," + item.getScoreParam() + ",false,droolsRuleLog,drools);\n";
                thenStr += "\t\tdrools.insert(scoreCardObj);";
                ruleItem = getCustomRule("card_init", 1000, null, thenStr);
                ruleCollection.getListItem().add(ruleItem);
                continue;
            }
            if (item.getList() != null && item.getList().size() > 0) {
                for (RuleScoreInfo child : item.getList()) {
                    //如果是scoreDetail的
                    //返回每个动作组的输出变量 * 该动作组的评分系数
                    if (child.getTreeId() != null && child.getTreeId().length() > 0) {
                        ruleName = "score_" + child.getTreeId();
                    } else {
                        ruleName = "score_" + StringUtils.generateTenUuid();
                    }
                    List<String> whenList = new ArrayList<String>();
                    String formualtemp = null;
                    String tempStr = null;
                    if ("1".equals(child.getIsOther())) {
                        whenStr = "";
                    } else {
                        whenStr = getScoreDetailDrl(item, child, "when", null, funcparamList,true);
                    }
                    if ("2".equals(child.getSectionType())) {
                        //formualtemp = "MathHelper.invokeMath($insertMap,metaMap,\"" + child.getFormula() + "\")";
                        formualtemp = ruleParseExpService.parseAction(child.getFormula(), false, this);
                    	if(StringUtils.isNotEmpty(formualtemp)) {
    	                	formualtemp = formualtemp.trim();
    	                	if(formualtemp.endsWith(";")) {
    	                		formualtemp = formualtemp.substring(0,formualtemp.lastIndexOf(";"));
    	                	}
                    	}else {
                    		formualtemp = "";
                    	}
                    } else if ("4".equals(child.getSectionType())) {//正向：系数*（变量-下限值）/（变量分数-下限）
                        tempStr = ",\n temp:(" + item.getScoreParam() + "*(this[\"" + item.getClassName() + "\"][\"" + item.getNameen() + "\"]-(" + child.getLowerVal() + "))/(" + child.getScoreVal() + "-(" + child.getLowerVal() + ")))";
                    } else if ("6".equals(child.getSectionType())) {//反向：系数*（上限-变量）/（上限-变量分数）
                        tempStr = ",\n temp:(" + item.getScoreParam() + "*(" + child.getUpperVal() + "-(this[\"" + item.getClassName() + "\"][\"" + item.getNameen() + "\"]))/(" + child.getUpperVal() + "-(" + child.getScoreVal() + ")))";
                    }
                    if (tempStr != null) {
                        whenStr += tempStr;
                        formualtemp = "temp";
                    }
                    thenStr = getScoreDetailDrl(item, child, "then", formualtemp, funcparamList,true);
                    whenList.add(whenStr);
                    ruleItem = getCustomRule(ruleName, priority, whenList, thenStr);
                    if (child.getTreeId() != null && child.getTreeId().length() > 0) {
                        ruleItem.getdThen().getLogsArr().add("\tdroolsRuleLog.addTracks(\""+child.getTreeId()+"\");");
                    }
                    ruleItem.setActivationGroup(groupName);
                    ruleCollection.getListItem().add(ruleItem);
                    priority--;
                }
            }else if(item.getTreeId()!=null){
            	ruleName = "score_" + item.getTreeId();
            	String name = item.getClassName() + "." + item.getNameen();
            	NumericFact data = new NumericFact(name);
            	CardFact fact = new CardFact(name, name, item.getScoreParam()+"","Double.parseDouble("+ data+".toString())");
            	List<String> whenList = new ArrayList<String>();
            	ruleItem = getCustomRule(ruleName, priority, whenList, fact.toString());
                ruleItem.getdThen().getLogsArr().add("\tdroolsRuleLog.addTracks(\""+item.getTreeId()+"\");");
            	ruleCollection.getListItem().add(ruleItem);
            	priority--;
            } else {
                List<String> whenList = new ArrayList<String>();
                thenStr = "ruleHelper.setValue";
                if ("List".equals("")) {
                    thenStr = "ruleHelper.insertValue";
                }
                if (summaryCount == 0) {
                    thenStr += "($insertMap,\"" + item.getClassName() + "." + item.getNameen() + "\",scoreCardObj.getValue());\n";
                    thenStr += "\t\truleHelper.setValue($insertMap,\"builtinParam."+score.getCode()+"\",\""+score.getName()+"\");\n";
                    ruleResultInfo = "scoreCardObj.value";
				}
//                else if(summaryCount==1){
//					thenStr += "($insertMap,\""+item.getClassName() +"." + item.getNameen() + "\",\""+score.getName()+"\");";
//                } 
                else {
                    //thenStr = "MathHelper.invokeMathToObj($insertMap,metaMap,\"" + item.getClassName() + "." + item.getNameen() + "\",\"" + item.getFormula() + "\");";
                	String formualtemp = ruleParseExpService.parseAction(item.getFormula(), false, this);
                	if(StringUtils.isNotEmpty(formualtemp)) {
	                	formualtemp = formualtemp.trim();
	                	if(formualtemp.endsWith(";")) {
	                		formualtemp = formualtemp.substring(0,formualtemp.lastIndexOf(";"));
	                	}
                	}else {
                		formualtemp = "null";
                	}
                	thenStr = "ruleHelper.setValue($insertMap,\"" + item.getClassName() + "." + item.getNameen() + "\"," + formualtemp + ");";
                }
                groupName = "";
                summaryCount++;
                ruleName = "score_" + StringUtils.generateTenUuid();
                ruleItem = getCustomRule(ruleName, priority, whenList, thenStr);
                ruleItem.setRuleResultInfo(ruleResultInfo);
                ruleItem.setActivationGroup(groupName);
                ruleCollection.getListItem().add(ruleItem);
                priority--;
            }
        }
        //规则输出描述（card_ouputDesc）-998
        List<String> whenList = new ArrayList<String>();
        whenList.add("scoreCardObj.getIsOut()!=null && scoreCardObj.getIsOut()");
        String actionStr = "\tscoreCardObj.inInsertMap($insertMap);";
        RuleItem rule = getCustomRule("card_ouputDesc", -998, whenList, actionStr);
        ruleCollection.getListItem().add(rule);
        
        //规则对象撤销 (card_end)-999
        whenList = new ArrayList<String>();
        actionStr = "drools.retract(scoreCardObj);";
        rule = getCustomRule("card_end", -999, whenList, actionStr);
        ruleCollection.getListItem().add(rule);
        
        //写入DRL文件
        return DroolsUtils.convert2DrlFunc(ruleCollection, null, RuleCollection.RULESCORE, null);
    }
    public String getScoreDetailDrl(ScoreItem item, RuleScoreInfo child, String type, String formultemp,List<RuleDataparams> funcparamList,Boolean isJavaFunc) {
        String retStr = "";
        if (type.equals("when")) {
//            retStr = "ruleHelper.getValue($insertMap,\"" + item.getClassName() + "." + item.getNameen() + "\")";
        	if("1".equals(item.getIsfuncparam())) {
				//收集函数变量
				RuleDataparams ruleDataparams = new RuleDataparams();
				ruleDataparams.setClassName(item.getClassName());
				ruleDataparams.setName(item.getNameen());
				funcparamList.add(ruleDataparams);
    		}
        	if(isJavaFunc!=null&&isJavaFunc) {
        		retStr = genernalJavaStr(item.getClassName(),item.getNameen(),item.getIsfuncparam(),item.getDataType());
        	}else {
        		retStr = genernalWhenStr(item.getClassName(),item.getNameen(),item.getIsfuncparam());
        	}
            if (item.getPosition() != null) {
                retStr += ".get(" + item.getPosition() + ")";
            }
            if (item.getDataType().equals("String")) {
                String symbol = "==";
                if (StringUtils.isEmpty(item.getDomain())) {//字符型
                    //修改字符类型生成DRL条件
                    if (child.getSymbol().equals("startsWith") || child.getSymbol().equals("endsWith") || child.getSymbol().equals("contains")) {
                        retStr += "." + child.getSymbol() + "(\"" + child.getContrastVals() + "\")";
                    } else if ( (child.getSymbol().equals("==") || child.getSymbol().equals("!=")) && (isJavaFunc==null||!isJavaFunc)) {
                        if (child.getContrastVals().length() == 0) {
                            retStr += child.getSymbol() + "null";
                        } else {
                            retStr += child.getSymbol() + "\"" + child.getContrastVals() + "\"";
                        }
                    } else if (child.getSymbol().equals("==") && isJavaFunc!=null&&isJavaFunc) {
                           retStr += ".equals(\""+child.getContrastVals()+"\")";
                    } else if (child.getSymbol().equals("!=")  && isJavaFunc!=null&&isJavaFunc ) {
                        retStr = "!"+retStr+".equals(\""+child.getContrastVals()+"\")";
                    } else {
                        retStr += child.getSymbol() + "\"" + child.getContrastVals() + "\"";
                    }

                } else {//枚举型
                    String result = child.getContrastVals();
                    if(isJavaFunc!=null&&isJavaFunc) {
	                    symbol = child.getSymbol().equals("0") ? "!" : "";
	                	retStr = symbol+"Arrays.asList("+ result.substring(1, result.length() - 1) +").contains("+retStr+")";
                	}else {
                		symbol = child.getSymbol().equals("0") ? " not in " : " in ";
                		retStr = retStr + symbol + "(" + result.substring(1, result.length() - 1) + ")";
                	}
                    
                }
            } else if (item.getDataType().equals("Boolean")) {
                if (child.getContrastVals() != null) {
                    retStr = retStr + "==" + (child.getContrastVals().equals("1") ? "true" : "false");
                }
            } else if (item.getDataType().equals("Date")) {
                String temp = retStr;
                if(isJavaFunc!=null&&isJavaFunc) {
	                if (!StringUtils.isEmpty(child.getLowerOpt()) && !StringUtils.isEmpty(child.getUpperOpt())) {
	                    retStr = temp + ".compareTo(\""+child.getLowerVal() +"\") "+child.getLowerOpt() + " 0 ";
	                    retStr += " && " + temp + ".compareTo(\""+child.getUpperVal() +"\") "+ child.getUpperOpt() + " 0 ";
	                } else if (!StringUtils.isEmpty(child.getLowerOpt()) && !StringUtils.isEmpty(child.getLowerVal())) {
	                	retStr = temp + ".compareTo(\""+child.getLowerVal() +"\") "+child.getLowerOpt() + " 0 ";
	                } else if (!StringUtils.isEmpty(child.getUpperOpt()) && !StringUtils.isEmpty(child.getUpperVal())) {
	                	retStr = temp + ".compareTo(\""+child.getUpperVal() +"\") "+ child.getUpperOpt() + " 0 ";
	                }
                }else {
	                if (!StringUtils.isEmpty(child.getLowerOpt()) && !StringUtils.isEmpty(child.getUpperOpt()) && !StringUtils.isEmpty(child.getUpperVal())) {
	                    retStr = temp + child.getLowerOpt() + "\"" + child.getLowerVal() + "\"";
	                    retStr += " && " + temp + child.getUpperOpt() + "\"" + child.getUpperVal() + "\"";
	                } else if (!StringUtils.isEmpty(child.getLowerOpt()) && !StringUtils.isEmpty(child.getLowerVal())) {
	                    retStr = temp + child.getLowerOpt() + "\"" + child.getLowerVal() + "\"";
	                } else if (!StringUtils.isEmpty(child.getUpperOpt()) && !StringUtils.isEmpty(child.getUpperVal())) {
	                    retStr = temp + child.getUpperOpt() + "\"" + child.getUpperVal() + "\"";
	                }
                }
            } else {
                String temp = retStr;
                if (StringUtils.isNotEmpty(child.getLowerOpt())&&StringUtils.isNotEmpty(child.getLowerVal()) 
                		&&StringUtils.isNotEmpty(child.getUpperVal()) && StringUtils.isNotEmpty(child.getUpperOpt())) {
                    retStr = temp + child.getLowerOpt() + child.getLowerVal();
                    retStr += " && " + temp + child.getUpperOpt() + child.getUpperVal();
                } else if (!StringUtils.isEmpty(child.getLowerOpt()) && !StringUtils.isEmpty(child.getLowerVal())) {
                    retStr = temp + child.getLowerOpt() + child.getLowerVal();
                } else if (!StringUtils.isEmpty(child.getUpperOpt()) && !StringUtils.isEmpty(child.getUpperVal())) {
                    retStr = temp + child.getUpperOpt() + child.getUpperVal();
                }
            }
        } else if (type.equals("then")) {
        	if(isJavaFunc!=null&&isJavaFunc) {
                if (formultemp != null) {
                    retStr = "\tscoreCardObj.addCardItem(\"" + item.getClassName() + "." + item.getNameen() + "\",\"" + item.getNamecn() + "\",\"" + child.getScopeDesc() + "\"," + item.getScoreParam() + ",Double.parseDouble(("+ formultemp+").toString()));";
                } else {
                	retStr = "\tscoreCardObj.addCardItem(\"" + item.getClassName() + "." + item.getNameen() + "\",\"" + item.getNamecn() + "\",\"" + child.getScopeDesc() + "\"," + item.getScoreParam() + "," + child.getScoreVal() + ",\""+child.getLabel()+"\");";
                }
        	}else {
                if (formultemp != null) {
                    retStr = "scoreCardObj.addCardItem(\"" + item.getClassName() + "." + item.getNameen() + "\",\"" + item.getNamecn() + "\",\"" + child.getScopeDesc() + "\"," + item.getScoreParam() + ",Double.parseDouble(("+ formultemp+").toString()));";
                } else {
                	retStr = "scoreCardObj.addCardItem(\"" + item.getClassName() + "." + item.getNameen() + "\",\"" + item.getNamecn() + "\",\"" + child.getScopeDesc() + "\"," + item.getScoreParam() + "," + child.getScoreVal() + ",\""+child.getLabel()+"\");";
                }
        	}

        }
        return retStr;
    }

    private RuleItem getCustomRule(String ruleName, int priority, List<String> whenList, String actionStr) {
        RuleItem rule = new RuleItem();
        rule.setEnabled("on");
        rule.setRuleName(ruleName);
        rule.setSalience(priority);
        DWhen dWhen = new DWhen();
        if (whenList != null) {
            List<Fact> factList = new ArrayList<Fact>();
            for (int i = 0; i < whenList.size(); i++) {
                String whenStr = whenList.get(i);
                if (i == 0) {
                    BlankFact obj = new BlankFact();
                    obj.setFactType("score");
                    obj.setContent(whenStr);
                    factList.add(obj);
                } else {
                    Fact fact = new Fact();
                    fact.setContent(whenStr);
                    factList.add(fact);
                }
            }
            dWhen.setFactList(factList);
        }
        DThen dThen = new DThen();
        Action action = new Action();
        action.setContent(actionStr);
        dThen.getListAction().add(action);
        rule.setdWhen(dWhen);
        rule.setdThen(dThen);
        return rule;
    }

    /**
     * 发布版本
     */
    public void updateVersion(RuleManage ruleManage) throws BizException {

        RuleScore con = new RuleScore();
        con.setManageId(ruleManage.getId());
        con.setVersion(ruleManage.getOldVersion());
        List<RuleScore> ruleScoreList = this.findList(con);

        RuleScoreInfo infoCon = new RuleScoreInfo();
        infoCon.setManageId(ruleManage.getId());
        infoCon.setVersion(ruleManage.getOldVersion());
        List<RuleScoreInfo> ruleScoreInfoList = ruleScoreInfoService.findList(infoCon);

        // 收集引用数据
        Map<String, RuleReferenceData> refMap = new HashMap();
        String key = "";
        String paramType = "";
        for (RuleScore item : ruleScoreList) {
            key = item.getClassName() + "|" + item.getNameen();
            paramType = "in";
            if ("scoreSummary".equals(item.getContentType())) {
                paramType = "out";
            }
            key += "|" + paramType;
            ruleReferenceDataService.collectCommonData(item, key, paramType, ruleManage, refMap);
        }
        //保存数据数据
        this.ruleReferenceDataService.saveReferenceData(refMap);
        this.insertBatch(ruleScoreList, new String[]{"id", "version"}, new Object[]{null, ruleManage.getVersion()}, true);
        if (ruleScoreInfoList.size() > 0)
            ruleScoreInfoService.insertBatch(ruleScoreInfoList, new String[]{"id", "version"}, new Object[]{null, ruleManage.getVersion()}, true);
    }

    /**
     * 评分模型复制
     * @param manage 旧版ruleManang 
     * @param manage 新版newRule 已保存
     */
    public void copyRule(RuleManage manage,RuleManage newRule) throws BizException {
        RuleScore con = new RuleScore();
        con.setManageId(manage.getId());
        con.setVersion(manage.getVersion());
        List<RuleScore> ruleScoreList = this.findList(con);

        // 收集引用数据
        Map<String, RuleReferenceData> refMap = new HashMap();
        String key = "";
        String paramType = "";
        for (RuleScore item : ruleScoreList) {
            key = item.getClassName() + "|" + item.getNameen();
            paramType = "in";
            if ("scoreSummary".equals(item.getContentType())) {
                paramType = "out";
            }
            key += "|" + paramType;
            ruleReferenceDataService.collectCommonData(item, key, paramType, newRule, refMap);
        }
        //保存数据数据
        this.ruleReferenceDataService.saveReferenceData(refMap);

        RuleScoreInfo infoCon = new RuleScoreInfo();
        infoCon.setManageId(manage.getId());
        infoCon.setVersion(manage.getVersion());
        List<RuleScoreInfo> ruleScoreInfoList = ruleScoreInfoService.findList(infoCon);

        this.insertBatch(ruleScoreList, new String[]{"id", "manageId", "version"}, new Object[]{null, newRule.getId(), newRule.getVersion()}, true);
        if (!ruleScoreInfoList.isEmpty()) {
            ruleScoreInfoService.insertBatch(ruleScoreInfoList, new String[]{"id", "manageId", "version"}, new Object[]{null, newRule.getId(), newRule.getVersion()}, true);
        }
//        RuleVersioninfo verCon = new RuleVersioninfo();
//        verCon.setManageId(manage.getId());
//        verCon.setVersion(manage.getVersion());
//        List<RuleVersioninfo> verList = ruleVersioninfoService.findList(verCon);
//        if (verList == null || verList.size() == 0) {
//            throw new BizException("E-100001");
//        }
//        RuleVersioninfo verInfo = verList.get(0);
//        verInfo.setId(null);
//        verInfo.setManageId(newRule.getId());
//        verInfo.setVersion(newRule.getVersion());
//        try {
//            String ruleContent = verInfo.getRuleContent();
//            ruleContent = ruleContent.replaceAll(manage.getCode() + manage.getVersion(), newRule.getCode() + newRule.getVersion());
//            ruleContent = ruleContent.replaceAll(manage.getCode() + "_" + manage.getVersion(), newRule.getCode() + "_" + newRule.getVersion());
//            //verInfo.setStrRuleContent(ruleContent);
//            verInfo.setRuleContent(ruleContent);
//            ruleVersioninfoService.save(verInfo);
//        } catch (Exception e) {
//            throw new BizException(e, "E-000500");
//        }
    }
    
	@Override
	public void clearVersion(RuleManage ruleManage,List<String> versions) {
		if(versions!=null&&versions.size()>0) {
			Map<String,Object> map = new HashMap<String,Object>();
			map.put("projectCode", ruleManage.getProjectCode());
			map.put("manageId", ruleManage.getId());
			map.put("versions", versions);
			this.dao.deleteByMutilVersion(map);
			this.ruleScoreInfoService.deleteByMutilVersion(map);
		}
	}

	@Override
	public void updateSetParam(String manageId, RuleSetParamInfo newSetParamInfo,RuleSetParamInfo oldSetParamInfo, boolean setFlag) throws Exception {
		  RuleManage ruleManage =this.ruleManageService.get(manageId);

	      RuleScore scoreCon = new RuleScore();
	      scoreCon.setManageId(manageId);
	      scoreCon.setVersion(ruleManage.getActiveVersion());
	      List<RuleScore> scoreItems = this.findList(scoreCon);
	      boolean  flag  =false;
	      for (RuleScore ruleScore :scoreItems) {
			  if (setFlag) {
				  if (ruleScore.getContentType()!=null &&ruleScore.getContentType().equals("scoreSummary")) {
					 String formul = ruleScore.getFormula().replace(oldSetParamInfo.getCode()+".", newSetParamInfo.getCode()+"."); 
					 ruleScore.setFormula(formul);						 
				  }	
				  if (!ruleScore.getClassName().equals("InitialScore")&& ruleScore.getClassName().equals(oldSetParamInfo.getCode())) {
					  ruleScore.setClassName(newSetParamInfo.getCode());
					  flag  =true;
					  this.dao.update(ruleScore);
				  }
				 
			  }else {
				  if (ruleScore.getContentType()!=null &&ruleScore.getContentType().equals("scoreSummary")) {
					  String formul = ruleScore.getFormula().replace("."+oldSetParamInfo.getCode(), "."+newSetParamInfo.getCode()); 
					  ruleScore.setFormula(formul);		
				  }
				  if (ruleScore.getNameen().equals(oldSetParamInfo.getCode())) {

					  ruleScore.setNameen(newSetParamInfo.getCode());
					  ruleScore.setNamecn(newSetParamInfo.getName());
					  flag = true;
					  this.dao.update(ruleScore);
				  }
				
			 }
			  
	      }
	      if (!flag) return ;
	      RuleScoreInfo scoreInfoCon = new RuleScoreInfo();
	      scoreInfoCon.setManageId(manageId);
	      scoreInfoCon.setVersion(ruleManage.getActiveVersion());
	      List<RuleScoreInfo> scoreInfoItems = ruleScoreInfoService.findList(scoreInfoCon);
	      List<ScoreItem> resultList = new  ArrayList<>();
	      for (int i= scoreItems.size()-1;i>-1;i--) {
	    	  RuleScore ruleScore= scoreItems.get(i);
	            ScoreItem item = new ScoreItem();
	            ConvertUtils.register(new DateConverter(null), java.util.Date.class);
	            BeanUtils.copyProperties(item, ruleScore);
	            if (item.getContentType().equals(CommonEnum.ScoreModelType.scoreDetail.toString()) && !item.getNameen().equals("initialScore")) {
	                for (RuleScoreInfo ruleScoreInfo : scoreInfoItems) {
	                    if (item.getTreeId().equals(ruleScoreInfo.getParentTreeId()))
	                        item.getList().add(ruleScoreInfo);
	                }
	            }
	            resultList.add(item);
	      }

	       List<RuleDataparams> funcparamList = new ArrayList<RuleDataparams>();
	       String context = writeDrl(ruleManage, resultList,funcparamList);
		   RuleVersioninfo  versInfo  = new RuleVersioninfo();
		   versInfo.setManageId(ruleManage.getId());
		   versInfo.setVersion(ruleManage.getActiveVersion());
		   List<RuleVersioninfo> vList =	this.ruleVersioninfoService.findList(versInfo);
		   if (vList != null && vList.size()>0) {
		    	RuleVersioninfo  ruleVer = vList.get(0);
		    	ruleVer.setRuleContent(context);
		    	this.ruleVersioninfoService.save(ruleVer);
		   }
		  
	}
	
	
	
}
